import React, { useEffect, useRef } from "react";
import * as d3 from "d3";

const unemployment = [
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-01-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-02-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-03-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-04-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-05-01",
    unemployment: 3.7,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-06-01",
    unemployment: 9.7,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-07-01",
    unemployment: 0.7,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-08-01",
    unemployment: 3.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-09-01",
    unemployment: 7.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-10-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-11-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, LD Met Div",
    date: "2000-12-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-01-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-02-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-03-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-04-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-05-01",
    unemployment: 2.7,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-06-01",
    unemployment: 2.7,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-07-01",
    unemployment: 2.7,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-08-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-09-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-10-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-11-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, MD Met Div",
    date: "2000-12-01",
    unemployment: 2.6,
  },
  {
    division: "Bethesda-Rockville-Frederick, ND Met Div",
    date: "2000-01-01",
    unemployment: 2.7,
  },
  {
    division: "Bethesda-Rockville-Frederick, ND Met Div",
    date: "2000-02-01",
    unemployment: 2.7,
  },
  {
    division: "Bethesda-Rockville-Frederick, ND Met Div",
    date: "2000-03-01",
    unemployment: 2.8,
  },
  {
    division: "Bethesda-Rockville-Frederick, ND Met Div",
    date: "2000-04-01",
    unemployment: 2.8,
  },
  {
    division: "Bethesda-Rockville-Frederick, ND Met Div",
    date: "2000-05-01",
    unemployment: 2.9,
  },
  {
    division: "Bethesda-Rockville-Frederick, ND Met Div",
    date: "2000-06-01",
    unemployment: 3,
  },
  {
    division: "Bethesda-Rockville-Frederick, ND Met Div",
    date: "2000-07-01",
    unemployment: 3.1,
  },
  {
    division: "Bethesda-Rockville-Frederick, ND Met Div",
    date: "2000-08-01",
    unemployment: 3.3,
  },
];

const UnemploymentChart = () => {
  const svgRef = useRef();

  useEffect(() => {
    // 清除之前的图表内容
    d3.select(svgRef.current).selectAll("*").remove();

    // 1. 数据预处理
    const data = unemployment.map((d) => ({
      ...d,
      date: new Date(d.date),
    }));

    // 设置图表的尺寸
    const margin = { top: 20, right: 80, bottom: 50, left: 50 };
    const width = 800 - margin.left - margin.right;
    const height = 400 - margin.top - margin.bottom;

    // 创建 SVG 容器
    const svg = d3
      .select(svgRef.current)
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom);

    const chartArea = svg
      .append("g")
      .attr("transform", `translate(${margin.left},${margin.top})`);

    // 创建缩放比例
    const xScale = d3
      .scaleTime()
      .domain(d3.extent(data, (d) => d.date))
      .range([0, width]);

    const yScale = d3
      .scaleLinear()
      .domain([
        d3.min(data, (d) => d.unemployment) - 0.5,
        d3.max(data, (d) => d.unemployment) + 0.5,
      ])
      .range([height, 0]);

    // 创建颜色比例（根据 division）
    const colorScale = d3
      .scaleOrdinal()
      .domain([...new Set(data.map((d) => d.division))])
      .range(d3.schemeCategory10);

    // 定义 x 和 y 轴
    const xAxis = d3.axisBottom(xScale).tickFormat(d3.timeFormat("%Y-%m"));
    const yAxis = d3.axisLeft(yScale);

    // 添加 x 轴
    chartArea
      .append("g")
      .attr("class", "x-axis")
      .attr("transform", `translate(0,${height})`)
      .call(xAxis)
      .selectAll("text")
      .attr("transform", "rotate(-45)")
      .style("text-anchor", "end");

    // 添加 y 轴
    chartArea.append("g").attr("class", "y-axis").call(yAxis);

    // 按 division 分组数据
    const dataNest = d3.groups(data, (d) => d.division);

    // 绘制折线
    const line = d3
      .line()
      .x((d: any) => xScale(d.date))
      .y((d: any) => yScale(d.unemployment));

    const lines = chartArea
      .selectAll(".line")
      .data(dataNest)
      .enter()
      .append("path")
      .attr("class", "line")
      .attr("d", (d: any) => line(d[1]))
      .attr("stroke", (d: any) => colorScale(d[0]) as any)
      .attr("stroke-width", 2)
      .attr("fill", "none");

    // 添加图例
    const legend = chartArea
      .selectAll(".legend")
      .data(dataNest)
      .enter()
      .append("g")
      .attr("class", "legend")
      .attr("transform", (d, i) => `translate(0, ${i * 20})`);

    legend
      .append("rect")
      .attr("x", width + 10)
      .attr("width", 10)
      .attr("height", 10)
      .style("fill", (d) => colorScale(d[0]) as any);

    legend
      .append("text")
      .attr("x", width + 25)
      .attr("y", 9)
      .attr("dy", ".35em")
      .text((d) => d[0]);

    // 创建 tooltip 组
    const tooltip = chartArea
      .append("g")
      .attr("class", "tooltip")
      .style("display", "none");

    tooltip
      .append("rect")
      .attr("class", "tooltip-box")
      .attr("x", 0)
      .attr("y", 0)
      .attr("width", 120)
      .attr("height", 50)
      .attr("fill", "white")
      .attr("stroke", "black")
      .attr("opacity", 0.8);

    const tooltipText = tooltip
      .append("text")
      .attr("class", "tooltip-text")
      .attr("x", 5)
      .attr("y", 15);

    const tooltipValue = tooltip
      .append("text")
      .attr("class", "tooltip-value")
      .attr("x", 5)
      .attr("y", 35);

    // 创建一个用于捕获鼠标事件的透明矩形
    chartArea
      .append("rect")
      .attr("class", "overlay")
      .attr("width", width)
      .attr("height", height)
      .style("fill", "none")
      .style("pointer-events", "all")
      .on("mouseover", () => tooltip.style("display", null))
      .on("mouseout", () => tooltip.style("display", "none"))
      .on("mousemove", function (event) {
        const mouse = d3.pointer(event);
        const mouseDate = xScale.invert(mouse[0]);

        // 查找最近的线
        const closestLine = d3.least(dataNest, ([division, values]) => {
          const bisectDate = d3.bisector((d: any) => d.date).center;
          const idx = bisectDate(values, mouseDate);
          const closestPoint = values[idx];

          // 考虑横向（时间）和纵向（失业率）的距离
          const distance = Math.sqrt(
            Math.pow(xScale(closestPoint.date) - mouse[0], 2) +
              Math.pow(yScale(closestPoint.unemployment) - mouse[1], 2)
          );
          return distance;
        });

        if (closestLine) {
          const [division, values] = closestLine;
          const bisectDate = d3.bisector((d: any) => d.date).center;
          const idx = bisectDate(values, mouseDate);
          const closestPoint = values[idx];

          // 更新 tooltip 的位置和内容
          tooltip.attr(
            "transform",
            `translate(${xScale(closestPoint.date)},${yScale(
              closestPoint.unemployment
            )})`
          );

          tooltipText.text(
            `Date: ${d3.timeFormat("%Y-%m")(closestPoint.date)}`
          );
          tooltipValue.text(`${division}: ${closestPoint.unemployment}`);
        }
      });

    // 清理副作用
    return () => {
      d3.select(svgRef.current).selectAll("*").remove();
    };
  }, []);

  return (
    <div>
      <h1>各地区失业率折线图</h1>
      <svg ref={svgRef}></svg>
    </div>
  );
};

export default UnemploymentChart;
